package com.atguigu.lease.app.service.impl;

import com.alibaba.fastjson2.JSON;
import com.atguigu.lease.app.mapper.UserInfoMapper;
import com.atguigu.lease.app.service.UserInfoService;
import com.atguigu.lease.app.service.UserLoginService;
import com.atguigu.lease.model.bean.UserInfo;
import com.atguigu.lease.model.dto.app.LoginSubmitDto;
import com.atguigu.lease.model.utils.HttpUtils;
import com.atguigu.lease.model.utils.JwtUtil;
import com.atguigu.lease.model.utils.ValidateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.RandomUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class UserLoginServiceImpl implements UserLoginService {



    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    UserInfoService userInfoService;

    @Autowired
    private UserInfoMapper userInfoMapper;


    @Override
    public void getCode(String phone) {
        //1.验证码手机格式
        ValidateUtil.phoneValidate(phone);
        //2.验证手机号获取验证码的频率，表单重复提交 刷短信
        //表单重复提交：一分钟之内只能获取一次验证码：setnx当键不存在时才设置
        String intervalKey = "stgy:login:interval:"+phone;
        if (!stringRedisTemplate.opsForValue().setIfAbsent(intervalKey,"1",1, TimeUnit.MINUTES)){
            //key设置失败，表示一分钟内这个手机号已经获取过验证码了，不能重复获取了
            Long remainingTime = stringRedisTemplate.getExpire(intervalKey);

            throw new RuntimeException("请求过于频繁，请 " + remainingTime + " 秒后再试");

        }
        //刷短信：一天内只能获取五次验证码
        String countKey = "stgy:login:count:" + phone;
        String count = stringRedisTemplate.opsForValue().get(countKey);


        //3.生成验证码调用点三方接口给手机号发短信
        String code = RandomUtils.nextInt(100000,999999)+"";
        //调用第三方接口发送验证码的业务方法
        System.out.println("code:"+ code);
        //sendMsg(phone,code);
        //4.短信发送成功： 缓存验证码的redis(过期时间10分钟) 更新手机号获取验证码的频率
         //缓存验证码到redis中（过期时间为10分钟）
        String key = "stgy:login:code:"+phone;
        stringRedisTemplate.opsForValue().setIfAbsent(key,code,10,TimeUnit.MINUTES);
        //更新手机号获取验证码的频率次数
        //一天内 手机号获取验证码的次数
        if (stringRedisTemplate.opsForValue().increment(countKey).longValue()==1l){
            //countKey 第一次自增，为这个键设置过期时间
            stringRedisTemplate.expire(countKey,1, TimeUnit.DAYS);


        }

    }

    @Override
    public String login(LoginSubmitDto loginSubmitDto) {

        //1.校验手机号号码格式是否正确
        String phone = loginSubmitDto.getPhone();
        ValidateUtil.phoneValidate(phone);

        //2、校验验证码是否正确： 和redis中缓存的比较
        String code = loginSubmitDto.getCode();
        //获取redis中缓存的 这个给手机号码的验证码
        String key = "stgy:login:code:"+phone;
        String redisCacheCode = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(code) || !code.equalsIgnoreCase(redisCacheCode)){
            throw new RuntimeException("验证码错误");
        }
        //删除验证码: 防止表单重复提交
        stringRedisTemplate.delete(key);
        //3、通过手机号获取用户信息
        UserInfo userInfo = userInfoMapper.selectOne(Wrappers.lambdaQuery(UserInfo.class)
                .eq(UserInfo::getPhone, phone));
        if (userInfo == null){
            // 3.1 获取失败： 手机号第一次访问stgy，帮助用户完成注册
            userInfo =new UserInfo();
            userInfo.setNickname("我是一个大鸭梨_"+
                    UUID.randomUUID().toString().substring(0,8));
            userInfo.setPhone(phone);
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            userInfo.setStatus(1);
            userInfo.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));

            System.out.println(userInfoService);
            userInfoService.save(userInfo);

        }
           // 3.2 获取成功： 第N次访问
        //4、根据查询到的用户 或者 新创建的用户 信息创建jwt返回
        return JwtUtil.createJwt(userInfo.getId(),userInfo.getNickname(),userInfo.getAvatarUrl());

    }

    private void sendMsg(String phone, String code) {
        // 第三方短信平台的服务器地址
        String host = "https://gyytz.market.alicloudapi.com";
        // 短信接口 资源路径
        String path = "//sms/smsSend";
        // 请求方式
        String method = "POST";
        // 我们购买 第三方平台 短信资源的 code码
        String appcode = "5e964bbb3d6e400f9e84458907e446d3";//开通服务后 买家中心-查看AppCode
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        // 请求参数map
        Map<String, String> querys = new HashMap<String, String>();
        //   短信模板： 只能修改验证码

        //int code = 236889;
        //querys.put("content", "【创信】你的验证码是："+code+"，3分钟内有效！");

        querys.put("param", "**code**:"+code+",**minute**:5");

        //   手机号
        querys.put("mobile", phone);


//smsSignId（短信前缀）和templateId（短信模板），可登录国阳云控制台自助申请。参考文档：http://help.guoyangyun.com/Problem/Qm.html

        querys.put("smsSignId", "2e65b1bb3d054466b82f0c9d125465e2");
        querys.put("templateId", "908e94ccf08b4476ba6c876d13f084ad");
        Map<String, String> bodys = new HashMap<String, String>();



        try {
            // 发送请求 并接收响应结果
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body： 获取响应体内容
            String body = EntityUtils.toString(response.getEntity());
            //解析json字符串： 判断短信发送成功还是失败
            Map map = JSON.parseObject(body, Map.class);
            /**
             "msg": "成功",
             "smsid": "16565614329364584123421",  //批次号。可通过该ID查询发送状态或者回复短信。API接口可联系客服获取。
             "code": "0",
             "balance": "1234"  //账户剩余次数
             }
             */
            Object returnStatus = map.get("msg");
            if(returnStatus!=null && "成功".equalsIgnoreCase(returnStatus.toString())){
                //验证码发送成功
                System.out.println("短信发送成功");
            }else{
                System.out.println("短信发送失败");
            }
            System.out.println("短信发送的结果："+ body);
            //System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
